/**
 * maintains redis client connections.
 */
var connectTimeout = 30 * 1000;
var redisMod = {};
var globalConfigs = require("../globalConfigs.js");

/**
 * build redis client object.
 * 
 * @param completedCallback
 *            callback function when completed
 */
function createRedisClient(completedCallback) {
    "use strict";
    
    var redisIP = globalConfigs.redisIP;
    var redisPort = globalConfigs.redisPort;
    var redis = require("redis");
    var rdClient = redis.createClient(redisPort, redisIP, {
        connect_timeout : connectTimeout,
        return_buffers : true
    });

    rdClient.on("connect", function() {
        console.log("redis connect ok, ip:%s, port:%d", redisIP, redisPort);
        completedCallback(rdClient);
    });

    rdClient.on("error", function(err) {
        console.log("redis connect failed, error:%s", err);
        completedCallback(null);
    });
}

function beginMulti(context) {
    "use strict";
    var redis = context.redis;
    if (context.multiObj) {
        context.multiDepth = context.multiDepth + 1;
        return;
    }

    context.multiObj = redis.multi();
    context.multiDepth = 1;
}

function endMulti(context, callback) {
    "use strict";

    if (!callback) {
        callback = function(err) {
            if (err) {
                console.error("endMulti failed:" + err);
            }
        };
    }

    context.multiDepth = context.multiDepth - 1;
    if (context.multiDepth > 0) {
        return;
    }

    var multi = context.multiObj;
    context.multiObj = null;
    multi.exec(callback);
}
/**
 * get redis client object.
 * 
 * @param context
 */
function setClient(context) {
    "use strict";
    if (!context.redis) {
        var index = (redisMod.index + 1) % redisMod.clientNumber;
        var redis = redisMod.clients[index];
        redisMod.index = index;

        context.beginMulti = function() {
            beginMulti(context);
        };
        context.endMulti = function(cb) {
            endMulti(context, cb);
        };

        context.redis = redis;
    }
    return context.redis;
}

redisMod.setClient = setClient;

redisMod.getContext = function() {
	var context = {};
	setClient(context);
	
	return context;
};

/**
 * startup redis client.
 * 
 * @param completedCallback
 *            callback functoin when completed
 */
redisMod.startup = function startup(completedCallback) {
    "use strict";
    var clientNumber = globalConfigs.redisClientNumber;
    var succeed = 0;
    var failed = 0;
    redisMod.clients = [];
    redisMod.index = 0;

    var createCallback = function(rdclient) {
        if (rdclient) {
            redisMod.clients.push(rdclient);
            succeed += 1;
            redisMod.clientNumber = succeed;
        } else {
            failed += 1;
        }

        if (succeed + failed === clientNumber) {
            completedCallback(succeed === clientNumber);
        }
    };

    for ( var i = 0; i < clientNumber; i += 1) {
        createRedisClient(createCallback);
    }
};

module.exports = redisMod;
